package com.mercury.base.util;

import org.apache.commons.lang3.StringUtils;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.function.Predicate;
import java.util.regex.Pattern;

/**
 * @author mercury
 * @date 2020/10/11 2:49 下午
 */
public class StringUtil {

    private static final Pattern INTEGER_PATTERN = Pattern.compile("^0|-?[1-9]\\d*$");
    private static final Pattern POSITIVE_INTEGER_PATTERN = Pattern.compile("^[1-9]\\d*$");

    //---------------------------------------------------------------------
    // General convenience methods for working with Strings
    //---------------------------------------------------------------------

    @Nullable
    public static String trim(String s) {
        return s == null ? null : s.trim();
    }

    @Nullable
    public static String trimAndToLowerCase(String s) {
        return s == null ? null : s.trim().toLowerCase();
    }

    @Nullable
    public static String trimAndRemoveLastChar(String text, Predicate<String> removeLastChar) {
        if (text == null) {
            return null;
        }
        text = trim(text);
        if (removeLastChar.test(text)) {
            return text.substring(0, text.length() - 1);
        }
        return text;
    }

    public static String humpToLine(String str) {
        return str.replaceAll("[A-Z]", "_$0").toLowerCase();
    }


    @Nonnull
    public static Integer parseInt(String text) {
        if (text == null) {
            throw new IllegalArgumentException("Text must not be null");
        }
        String trimmed = trim(text);
        return isHexNumber(trimmed) ? Integer.decode(trimmed) : Integer.valueOf(trimmed);
    }

    /**
     * 是否为整数：-1，0，1，2...
     */
    public static boolean isInteger(String text) {
        return text != null && INTEGER_PATTERN.matcher(trim(text)).matches();
    }

    /**
     * 是否为正整数：1，2，3...
     */
    public static boolean isPositiveInteger(String text) {
        return text != null && POSITIVE_INTEGER_PATTERN.matcher(trim(text)).matches();
    }

    /**
     * Determine whether the given {@code value} String indicates a hex number,
     * i.e. needs to be passed into {@code Integer.decode} instead of
     * {@code Integer.valueOf}, etc.
     */
    public static boolean isHexNumber(String value) {
        int index = (value.startsWith("-") ? 1 : 0);
        return value.startsWith("0x", index) || value.startsWith("0X", index) || value.startsWith("#", index);
    }

    /**
     * Determines if a string is empty (<code>null</code> or zero-length).
     */
    public static boolean isEmpty(CharSequence string) {
        return (string == null) || (string.length() == 0);
    }

    /**
     * Determines if a string is not empty (not null and not zero-length).
     */
    public static boolean isNotEmpty(CharSequence string) {
        return !isEmpty(string);
    }

    //---------------------------------------------------------------------
    // Convenience methods for working with formatted Strings
    //---------------------------------------------------------------------

    /**
     * 去除字符串里的所有空格
     */
    @Nullable
    public static String removeAllWhitespace(String s) {
        return s == null ? null : s.replaceAll(" ", "");
    }

    /**
     * 首字母大写
     */
    public static String capitalize(String str) {
        return changeFirstCharacterCase(str, true);
    }

    /**
     * 首字母小写
     */
    public static String uncapitalize(String str) {
        return changeFirstCharacterCase(str, false);
    }

    private static String changeFirstCharacterCase(String str, boolean capitalize) {
        if (isEmpty(str)) {
            return str;
        }

        char firstChar = str.charAt(0);
        char updatedChar;
        if (capitalize) {
            updatedChar = Character.toUpperCase(firstChar);
        } else {
            updatedChar = Character.toLowerCase(firstChar);
        }
        if (firstChar == updatedChar) {
            return str;
        }

        char[] chars = str.toCharArray();
        chars[0] = updatedChar;
        return new String(chars, 0, chars.length);
    }

    public static String stringOrSubstringAfterLast(String str, char c) {
        if (str == null) {
            return null;
        }
        int i = str.lastIndexOf(c);
        if (i != -1) {
            return str.substring(i + 1);
        }
        return str;
    }

    @Nullable
    public static String blankToNull(String value) {
        if (StringUtils.isBlank(value)) {
            return null;
        }
        return value;
    }

    public static boolean isAscIi(String str) {
        return str != null && str.getBytes().length == str.length();
    }

}
